package org.yfl.mbg.enhance.plugin;

import org.apache.commons.lang3.StringUtils;
import org.mybatis.generator.api.GeneratedXmlFile;
import org.mybatis.generator.api.IntrospectedColumn;
import org.mybatis.generator.api.IntrospectedTable;
import org.mybatis.generator.api.PluginAdapter;
import org.mybatis.generator.api.dom.java.*;
import org.mybatis.generator.api.dom.kotlin.KotlinFile;
import org.mybatis.generator.api.dom.kotlin.KotlinFunction;
import org.mybatis.generator.config.JavaModelGeneratorConfiguration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.yfl.mbg.enhance.constants.JpaConstants;
import org.yfl.mbg.enhance.utils.FileUtil;

import java.util.List;

/**
 * jpa组件生成插件
 * @author yanfeilin
 * @version 1.0.0
 * @date 2020/5/23 19:00
 */
public class GenJpaClassPlugin extends PluginAdapter {

    private static final Logger LOG = LoggerFactory.getLogger(GenJpaClassPlugin.class);

    @Override
    public boolean validate(List<String> warnings) {
        return true;
    }

    @Override
    public boolean modelBaseRecordClassGenerated(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {
        //检测domain已经存在
        if(FileUtil.domainFileExists(context,introspectedTable)){
            String domainName = introspectedTable.getTableConfiguration().getDomainObjectName();
            LOG.warn("{}已经存在，不再生成!",domainName);
            return false;
        }
        //继承base domain
        String baseDomainClsFullName = context.getProperty("generator.basedomain.clsfullname");
        if(StringUtils.isNotEmpty(baseDomainClsFullName)){
            topLevelClass.addImportedType(baseDomainClsFullName);
            topLevelClass.setSuperClass(baseDomainClsFullName);
        }

        //添加jpa注解
        topLevelClass.addImportedType(JpaConstants.TABLE_ANNO_CLASS);
        topLevelClass.addImportedType(JpaConstants.ENTITY_ANNO_CLASS);
        topLevelClass.addImportedType(JpaConstants.ID_ANNO_CLASS);
        topLevelClass.addImportedType(JpaConstants.COLUMN_ANNO_CLASS);

        topLevelClass.addAnnotation("@Entity");
        String tableName = introspectedTable.getTableConfiguration().getTableName();
        topLevelClass.addAnnotation("@Table(name=\""+tableName+"\")");
        return true;
    }

    @Override
    public boolean modelFieldGenerated(Field field, TopLevelClass topLevelClass, IntrospectedColumn introspectedColumn, IntrospectedTable introspectedTable, ModelClassType modelClassType) {
        //增加Column注解
        IntrospectedColumn priColumn = introspectedTable.getPrimaryKeyColumns().get(0);
        //主键列表
        String priColumnName = priColumn.getActualColumnName();
        String columnName = introspectedColumn.getActualColumnName();

        if(columnName.equals(priColumnName)){//该表格列是主键，添加@Id注解
           field.addAnnotation("@Id");
        }

        StringBuilder columnAnnoBuilder = new StringBuilder(128);
        columnAnnoBuilder.append("@Column(name=\"").append(columnName).append("\")");
        field.addAnnotation(columnAnnoBuilder.toString());
        return true;
    }

    private String getJavaModelPkg(){
        JavaModelGeneratorConfiguration modelGeneratorConfig = context.getJavaModelGeneratorConfiguration();
        String modelPkg = modelGeneratorConfig.getTargetPackage();
        return modelPkg;
    }

    @Override
    public boolean clientGenerated(Interface interfaze, IntrospectedTable introspectedTable) {
        if(FileUtil.daoFileExists(context,introspectedTable)){
            String daoFullClsName = introspectedTable.getMyBatis3JavaMapperType();
            LOG.warn("{}已经存在，不再生成!",daoFullClsName);
            return false;
        }
        String jpaBaseDaoClass = context.getProperty("generator.dao.jpa.baseCls");
        if(StringUtils.isEmpty(jpaBaseDaoClass)){
            jpaBaseDaoClass = JpaConstants.DEFAULT_JPA_BASEDAO_CLASS;
        }

        FullyQualifiedJavaType baseDaoType = new FullyQualifiedJavaType(jpaBaseDaoClass);
        //给base dao增加泛型参数
        String modelPkg = getJavaModelPkg();
        String domainSimpleClsName = introspectedTable.getTableConfiguration()
                .getDomainObjectName();
        String domainFullClsName = modelPkg+"."+domainSimpleClsName;
        FullyQualifiedJavaType domainType = new FullyQualifiedJavaType(domainFullClsName);
        baseDaoType.addTypeArgument(domainType);

        //id泛型
        String idCls = context.getProperty("generator.dao.jpa.IdCls");
        if(StringUtils.isEmpty(idCls)){
            idCls = "java.lang.Integer";
        }
        FullyQualifiedJavaType idType = new FullyQualifiedJavaType(idCls);
        baseDaoType.addTypeArgument(idType);

        interfaze.addImportedType(domainType);
        interfaze.addImportedType(idType);
        interfaze.addImportedType(baseDaoType);
        interfaze.addSuperInterface(baseDaoType);
        return true;
    }

    @Override
    public boolean sqlMapGenerated(GeneratedXmlFile sqlMap, IntrospectedTable introspectedTable) {
        return false;
    }

    @Override
    public boolean modelExampleClassGenerated(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {
        return false;
    }

    @Override
    public boolean modelRecordWithBLOBsClassGenerated(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {
        return false;
    }

    @Override
    public boolean clientInsertMethodGenerated(Method method, Interface interfaze, IntrospectedTable introspectedTable) {
        return false;
    }

    @Override
    public boolean clientBasicInsertMultipleMethodGenerated(Method method, Interface interfaze, IntrospectedTable introspectedTable) {
        return false;
    }

    @Override
    public boolean clientBasicUpdateMethodGenerated(Method method, Interface interfaze, IntrospectedTable introspectedTable) {
        return false;
    }

    @Override
    public boolean clientBasicInsertMethodGenerated(KotlinFunction kotlinFunction, KotlinFile kotlinFile, IntrospectedTable introspectedTable) {
        return false;
    }

    @Override
    public boolean clientUpdateByPrimaryKeyWithoutBLOBsMethodGenerated(Method method, Interface interfaze, IntrospectedTable introspectedTable) {
        return false;
    }

    @Override
    public boolean clientBasicUpdateMethodGenerated(KotlinFunction kotlinFunction, KotlinFile kotlinFile, IntrospectedTable introspectedTable) {
        return false;
    }

    @Override
    public boolean clientDeleteByPrimaryKeyMethodGenerated(Method method, Interface interfaze, IntrospectedTable introspectedTable) {
        return false;
    }

    @Override
    public boolean clientUpdateByPrimaryKeySelectiveMethodGenerated(Method method, Interface interfaze, IntrospectedTable introspectedTable) {
        return false;
    }

    @Override
    public boolean clientSelectByPrimaryKeyMethodGenerated(Method method, Interface interfaze, IntrospectedTable introspectedTable) {
        return false;
    }

    @Override
    public boolean clientBasicInsertMultipleHelperMethodGenerated(Method method, Interface interfaze, IntrospectedTable introspectedTable) {
        return false;
    }

    @Override
    public boolean clientBasicDeleteMethodGenerated(Method method, Interface interfaze, IntrospectedTable introspectedTable) {
        return false;
    }

    @Override
    public boolean clientBasicInsertMethodGenerated(Method method, Interface interfaze, IntrospectedTable introspectedTable) {
        return false;
    }

    @Override
    public boolean clientBasicCountMethodGenerated(Method method, Interface interfaze, IntrospectedTable introspectedTable) {
        return false;
    }

    @Override
    public boolean clientBasicSelectManyMethodGenerated(Method method, Interface interfaze, IntrospectedTable introspectedTable) {
        return false;
    }

    @Override
    public boolean clientBasicSelectOneMethodGenerated(Method method, Interface interfaze, IntrospectedTable introspectedTable) {
        return false;
    }

    @Override
    public boolean clientInsertSelectiveMethodGenerated(Method method, Interface interfaze, IntrospectedTable introspectedTable) {
        return false;
    }

    @Override
    public boolean modelPrimaryKeyClassGenerated(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {
        return false;
    }

}
